---
title: MediaLibrary
description: A library that provides access to the device's media library.
sourceCodeUrl: 'https://github.com/expo/expo/tree/main/packages/expo-media-library'
packageName: 'expo-media-library'
iconUrl: '/static/images/packages/expo-media-library.png'
platforms: ['android', 'ios']
---

import APISection from '~/components/plugins/APISection';
import { APIInstallSection } from '~/components/plugins/InstallSection';
import { AndroidPermissions, IOSPermissions } from '~/components/plugins/permissions';
import {
  ConfigReactNative,
  ConfigPluginExample,
  ConfigPluginProperties,
} from '~/ui/components/ConfigSection';
import { SnackInline } from '~/ui/components/Snippet';

`expo-media-library` provides access to the user's media library, allowing them to access their existing images and videos from your app, as well as save new ones. You can also subscribe to any updates made to the user's media library.

## Installation

<APIInstallSection />

## Configuration in app.json/app.config.js

You can configure `expo-media-library` using its built-in [config plugin](/config-plugins/introduction/) if you use config plugins in your project ([EAS Build](/build/introduction) or `npx expo run:[android|ios]`). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect.

<ConfigReactNative>

Learn how to configure the native projects in the [installation instructions in the `expo-media-library` repository](https://github.com/expo/expo/tree/main/packages/expo-media-library#installation-in-bare-react-native-projects).

</ConfigReactNative>

<ConfigPluginExample>

```json
{
  "expo": {
    "plugins": [
      [
        "expo-media-library",
        {
          "photosPermission": "Allow $(PRODUCT_NAME) to access your photos.",
          "savePhotosPermission": "Allow $(PRODUCT_NAME) to save photos.",
          "isAccessMediaLocationEnabled": true
        }
      ]
    ]
  }
}
```

</ConfigPluginExample>

<ConfigPluginProperties
  properties={[
    {
      name: 'photosPermission',
      platform: 'ios',
      description:
        'Sets the iOS `NSPhotoLibraryUsageDescription` permission message in **Info.plist**.',
      default: '"Allow $(PRODUCT_NAME) to access your photos."',
    },
    {
      name: 'savePhotosPermission',
      platform: 'ios',
      description:
        'Sets the iOS `NSPhotoLibraryAddUsageDescription` permission message in **Info.plist**.',
      default: '"Allow $(PRODUCT_NAME) to save photos."',
    },
    {
      name: 'isAccessMediaLocationEnabled',
      platform: 'android',
      description:
        'Sets whether or not to request the `ACCESS_MEDIA_LOCATION` permission on Android.',
      default: 'false',
    },
  ]}
/>

## Usage

<SnackInline label='Fetching albums and displaying assets' dependencies={['expo-media-library']}>

{/* prettier-ignore */}
```jsx
import { useState, useEffect } from 'react';
import { Button, Text, SafeAreaView, ScrollView, StyleSheet, Image, View, Platform } from 'react-native';
import * as MediaLibrary from 'expo-media-library';

export default function App() {
  const [albums, setAlbums] = useState(null);
  const [permissionResponse, requestPermission] = MediaLibrary.usePermissions();

  async function getAlbums() {
    if (permissionResponse.status !== 'granted') {
      await requestPermission();
    }
    const fetchedAlbums = await MediaLibrary.getAlbumsAsync({
      includeSmartAlbums: true,
    });
    setAlbums(fetchedAlbums);
  }

  return (
    <SafeAreaView style={styles.container}>
      <Button onPress={getAlbums} title="Get albums" />
      <ScrollView>
        {albums && albums.map((album) => <AlbumEntry album={album} />)}
      </ScrollView>
    </SafeAreaView>
  );
}

function AlbumEntry({ album }) {
  const [assets, setAssets] = useState([]);

  useEffect(() => {
    async function getAlbumAssets() {
      const albumAssets = await MediaLibrary.getAssetsAsync({ album });
      setAssets(albumAssets.assets);
    }
    getAlbumAssets();
  }, [album]);

  return (
    <View key={album.id} style={styles.albumContainer}>
      <Text>
        {album.title} - {album.assetCount ?? 'no'} assets
      </Text>
      <View style={styles.albumAssetsContainer}>
        {assets && assets.map((asset) => (
          <Image source={{ uri: asset.uri }} width={50} height={50} />
        ))}
      </View>
    </View>
  );
}

/* @hide const styles = StyleSheet.create({ ... }); */
const styles = StyleSheet.create({
  container: {
    flex: 1,
    gap: 8,
    justifyContent: 'center',
    ...Platform.select({
      android: {
        paddingTop: 40,
      },
    }),
  },
  albumContainer: {
    paddingHorizontal: 20,
    marginBottom: 12,
    gap: 4,
  },
  albumAssetsContainer: {
    flexDirection: 'row',
    flexWrap: 'wrap',
  },
});
/* @end */
```

</SnackInline>

## API

```js
import * as MediaLibrary from 'expo-media-library';
```

<APISection packageName="expo-media-library" apiName="MediaLibrary" />

## Permissions

### Android

The following permissions are added automatically through this library's `AndroidManifest.xml`.

<AndroidPermissions permissions={['READ_EXTERNAL_STORAGE', 'WRITE_EXTERNAL_STORAGE']} />

### iOS

The following usage description keys are used by this library:

<IOSPermissions
  permissions={['NSPhotoLibraryUsageDescription', 'NSPhotoLibraryAddUsageDescription']}
/>
